#pragma once
#include "Common.hpp"

template <class T>
class ObjectPool
//管理当前ThreadCache 对ThreadCache分配一块128KB的内存空间
{
public:
    T *New()
    {
        T *obj = nullptr;
        // 优先把换回来的内存块重复利用
        if (_freeList)
        {
            void *next = *((void **)_freeList); // 保存申请后的头指针
            obj = (T *)_freeList;               // 拿到内存地址后，将其强转为T*类型指针
            _freeList = next;                   // 更新头指针
        }
        else
        {
            // 剩余内存不够一个对象大小时，重新开大内存空间
            if (_remainBytes < sizeof(T))
            {
                // _remainBytes = 128 * 1024; // 申请128KB
                _remainBytes = 8 * 1024; // 申请8KB
                // 向操作系统申请一块
                _memory = static_cast<char *>(
                    ::mmap(nullptr,                // 让内核自己挑地址
                           _remainBytes,           // 要映射的字节数，必须是页大小的整数倍 128K/8192=16
                           PROT_READ | PROT_WRITE, // 可读可写
                           MAP_PRIVATE | MAP_ANONYMOUS,
                           -1, 0));
                if (_memory == MAP_FAILED)
                {
                    throw std::bad_alloc();
                }
            }
            obj = (T *)_memory; // 返回给obj
            size_t objSize = sizeof(T) < sizeof(void *) ? sizeof(void *) : sizeof(T);
            // objsize如果小于4/8 则直接给4/8 否则给T大小
            _memory += objSize;      // memory指向分割后的内存
            _remainBytes -= objSize; // 剩余大小减去objsize
        }
        // 对于自定义类型
        // 定位new，显式调用T的构造函数
        new (obj) T;
        // 在obj指向的内存上显式调用T的构造函数
        return obj;
    }
    void Delete(T *obj)
    {
        // 显式析构函数 清理对象
        obj->~T();
        // 头插
        *(void **)obj = _freeList;
        _freeList = obj;
    }

private:
    char *_memory = nullptr;   // 指向大块内存的指针，向系统申请的大块内存
    size_t _remainBytes = 0;   // 大块内存在切分过程中的剩余内存
    void *_freeList = nullptr; // 还回来过程中链接的自由链表的头指针
};